#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <syslog.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>


#include "../include/shm_server.h"
#include "../include/queries.h"
#include "../include/server.h"
#include "../databaseADT/databaseADT.h"
#include "../../common/include/common.h"
#include "../../common/include/general.h"
#include "../../common/include/split.h"
#include "../../common/include/menu.h"
#include "../../common/include/commonSHM.h"


#define PUB_KEY 500
#define SHMSZ 1024

shmADT pub;
int sndlistSM(shmADT s);

/* Externs de server.c */
extern char splitVal;
extern splitNode splits[MAX_SPLITS];
extern int doLC;

int
mainSM (void)
{
    int i, splitRet;

    if((pub = open_conn_shm(PUB_KEY, 1)) == 0)
        return fatal(   "ERROR: Can't open_conn_shm.\n"
                        "SOLUTION: Check PUB_KEY.\n");


    if ((i = getOnlineFreeID(NULL)) == -1)
        return fatal(   "ERROR: Can't get a free slot in split vec.\n"
                        "SOLUTION: Check MAX_SPLITS.\n");

    /* Handlers de SIGS */
    (void)signal(SIGINT, sighandLCSM);

    /* Actualizo online */
    modifyOnline(i, i, NULL, 1);

    /*Se splitea dependiendo de los parámetros.*/
    if (splitVal == 't')
        splitRet = split(listenPubSM, NULL, (void *)&splits[i].thread, splitVal,
                        endCiclesSM);
    else
        splitRet = split(listenPubSM, NULL, (void *)&splits[i].cID, splitVal,
                        endCiclesSM);

    if ( splitRet != 1)
        fatal(  "ERROR: Split failed.\n"
                "SOLUTION: Check SPLITS_QUANTITY.\n");

    readCommandsSM();

    return 0;
}

void *
listenPubSM(void *parmsLC)
{
    char msgbuf[SHMSZ]={0};
    char auxbuf[SHMSZ]={0};
    int splitRet;
    char *ptr = NULL;
    int cliID = 0, priv, aux, auxlen;
    shmADT privShm;

    while(doLC)
    {
        if(msgForServer(pub))
        {
            rcv_data_shm(pub, msgbuf);
            printf("recibi msg %s\n", msgbuf);

            ptr = strdup(msgbuf);

            clrtext(auxbuf, SHMSZ);
            sscanf(ptr, "0,%d,%d,%d,%d,%s", &cliID, &aux, &auxlen, &priv,auxbuf);

            if (cliID == 0)
                waitPckSM((void *)ptr);
            else if (!isFreeOnline(cliID))
            {
            	clrtext(msgbuf, SHMSZ);
                sprintf(msgbuf, "1,%d", IS_BUSY);
                if((privShm = open_conn_shm(priv, 0)) == NULL)
                    fatal("shared memory at failed\n");
                send_data_shm(privShm, msgbuf, strlen(msgbuf));
                /* TODO: cerrar esperando que el cliente lea */
                sleep(3);
                close_conn_shm(privShm);
                free(ptr);

            }
            else
            {
                /* Me fijo si es un commit.
                Si es, creo el .new para evitar conflictos. */
                if (canCommittSM(msgbuf))
                {
                    /* Actualizo online */
                    modifyOnline(cliID, cliID, NULL, 1);

                    /*Se splitea dependiendo de los parámetros.*/
                    if (splitVal == 't')
                        splitRet = split(waitPckSM, (void *)ptr,
                        (void *)&splits[cliID].thread, splitVal, endCiclesSM);
                    else
                        splitRet = split(waitPckSM, (void *)ptr,
                        (void *)&splits[cliID].cID, splitVal, endCiclesSM);

                    if ( splitRet != 1)
                    {
                        fatal(  "ERROR: Split failed.\n"
                                "SOLUTION: Check SPLITS_QUANTITY.\n");
                        doLC = 0;
                    }
                }
            }
        }
    }
    /*HACK: retorna void * */
    return (void *)NULL;
}

void
readCommandsSM(void)
{
    int i;
    char command[MAX_COMMAND_LEN+1] = {0};
    char * param;
    char * commands[] = {"registrar", "usuarios", "dir", "last10",
        "ulast10", "newDir", "salir"};
        int cant_comms = sizeof(commands) / sizeof(commands[0]);

        void (*pFunct[]) (char *)= {registrar, usuarios, dir, last10, ulast10,
            newDir, salirSM};

            fprintf (stdout, "\n<>: ");
            getLine (command, MAX_COMMAND_LEN, stdin);

            for (i=0 ; i < cant_comms+1 ; i++)
            {
                if (i == cant_comms)
                {
                    fprintf (stdout, "\nError: Invalid command\n<>: ");
                    getLine (command, MAX_COMMAND_LEN, stdin);
                    i = -1;
                }
                else if (strcmp (command, commands[i]) == 0)
                {
                    if(i == 6)
                        salirSM(param);

                    pFunct[i] (param);
                    fprintf (stdout, "\n<>: ");
                    getLine (command, MAX_COMMAND_LEN, stdin);
                    i = -1;
                }
            }

            return ;
}


int canCommittSM(char * msg)
{
    FILE * pfile;
    int com, shmKey;
    int size, logged;
    char params[50] = {0};
    char priv[50] = {0};
    char full[100] = {0};
    int type;
    char dir[FILE_LEN] = {0};
    char newpath[100] = {0};
    int len, back;
    char answ[FILE_LEN] = {0};
    char ans[SHMSZ] = {0};

    shmADT privShm;

//     aux deberia ser 0 ya que es un msg para server
    sscanf(msg, "0,%d,%d,%d,%d,%s", &logged, &com, &size, &shmKey, full);

//  TODO DEBUG
    printf("canComitt, msg: %s\n", msg);

    if (com != COM_COMMIT)
        return 1;

     getparamSM(full, params, priv);
//     le sumo 2 ya que ahora el full tiene 2 chars al
//  principio que es propio protocolo de sharedmemo

    /*TODO: DEBUG */
    printf("com: %d\n", com);
    getDirType(params, dir, &type);

    sprintf(newpath, "%s.new", dir);
    printf("NEW: %s\n", newpath);

    if((pfile = fopen(newpath, "r")) == NULL)
    {
        if (type == DEL_COMMIT)
            return 1;
        if (type == DEL_DIR_COMMIT)
            return 1;

        if((pfile = fopen(newpath, "w")) == NULL)
        {
            fatal ("file open failed\n");
            return -1;
        }

        if (fclose(pfile) == EOF)
        {
            fatal ("file close failed\n");
            return -1;
        }
        return 1;

    }

    /* TODO: Log Conflict */

    len = strlen(dir);
    sprintf(answ, "%d,%d,%d,%s", 1, WILL_UPDATE, len, dir);

    if((privShm = open_conn_shm(shmKey, 0)) == NULL)
        return fatal("shared memory at failed\n");

    len = strlen(answ);
    send_data_shm (privShm, answ, len);

    while(!msgForServer(privShm))
        ;

    clrtext(ans, SHMSZ);
    rcv_data_shm(privShm, ans);
    sscanf(ans, "%d", &back);
    printf("ENDSRV: %s\n", ans);
    if(back == COM_END)
        close_conn_shm(privShm);

    return 0;
}

void *
waitPckSM (void *ptr)
{
    char *msg = (char *)ptr;
    int com, privKey, logged;
    int size;
    char params[50] = {0};
    char priv[50] = {0};
    char full[100] = {0};
    int close = 1;

    sscanf(msg, "0,%d,%d,%d,%d,%s", &logged, &com,  &size, &privKey, full);

    if (logged == 0)
        close = 0;
    getparamSM(full, params, priv);


    /*TODO: DEBUG */
     printf("full: %s\nparams: %s\npriv: %s\n", full , params, priv);


    switch(com)
    {
        case COM_NAME:
            printf("ADDNAME\n");
            (void)addnameSM(priv, privKey);
            break;

        case COM_LIST:
//             TODO DEBUEG
            printf("LISTDIR\n");
            listdirsSM(full, privKey);
            break;

        case COM_ADD:
//             TODO DEBUEG
            printf("ADDDIR\n");
            (void)adddirSM(params, priv, privKey);
            break;

        case COM_REMOVE:
//             TODO DEBUEG
            printf("REMOVEDIR\n");
            (void)removedirSM(params, priv, privKey);
            break;

        case COM_CLOSE:
//             TODO DEBUEG
            printf("CLOSE\n");
            closesessSM(full);
            break;

        case COM_COMMIT:
//             TODO DEBUEG
            printf("COM_COMMIT\n");
            rcvCommitSM(params, priv, privKey);
            break;

        default:
            break;
    }

    free(ptr);

    if (close)
    {
        modifyOnline(logged, logged, NULL, 0);
        exitSplit(splitVal);
    }

    return NULL;
}

void fstconnSM (char * priv)
{
    return;
}

int addnameSM (char * name, int privKey)
{
    char msgbuf[SHMSZ] = {0};
    char r_msg[SHMSZ] = {0};
    char privKeyC[15] = {0};
    int com = 0, cliID;
    shmADT priv;

    sprintf(privKeyC, "%d", privKey);

    if((priv = open_conn_shm(privKey, 1)) == NULL)
    {
        fprintf(stderr, "error open shared memory\n");
        return -1;
    }

    if (addUser(name, privKeyC) == DB_INTERNAL_ERROR)
    {
        sprintf(msgbuf, "1,%d",COM_ERR);
        send_data_shm(priv, msgbuf, strlen(msgbuf));
        close_conn_shm(priv);
        return fatal(   "ERROR: Database error In addname.\n"
                        "SOLUTION: Check Database status.\n");
    }

    switch(DBconnect(name))
    {
        case DB_INTERNAL_ERROR:
            sprintf(msgbuf, "1,%d",COM_ERR);
            send_data_shm(priv, msgbuf, strlen(msgbuf));
            //close_conn_shm(priv);
            return fatal(   "ERROR: Database error In addname.\n"
                            "SOLUTION: Check Database status.\n");
            break;

        case DB_ALREADY_EXISTS:
        	clrtext(msgbuf, SHMSZ);
            sprintf(msgbuf, "1,%d",COM_ERR);
            send_data_shm(priv, msgbuf, strlen(msgbuf));
           // close_conn_shm(priv);
            fprintf(stderr, "ERROR: User %s already logged\n", name);
            return fatal(   "SOLUTION: If this persist, ban him. :)\n");
            break;

        case DB_NO_SLOTS:
            sprintf(msgbuf, "1,%d",COM_ERR);
            send_data_shm(priv, msgbuf, strlen(msgbuf));
            //close_conn_shm(priv);
            return fatal(   "ERROR: No more slots available.\n"
                            "SOLUTION: Check MAX_SPLITS.\n");
            break;

        default:
            break;
    }

    cliID = userID(name);
    
    sprintf(msgbuf, "1,%d,%d", COM_ACK, cliID);

    send_data_shm(priv, msgbuf, strlen(msgbuf));

    addLog(privKeyC, "Logged in");

    while(!msgForServer(priv))
        ;
    clrtext(r_msg, SHMSZ);
    rcv_data_shm (priv, r_msg);
    sscanf(r_msg, "0,%d", &com);

    if (com == COM_ACK)
        close_conn_shm(priv);

    return 1;
}

void
listdirsSM (char *priv, int shmKey)
{
    char answ[50] = {0};
//  char serv_priv[50] = {0};
    char r_msg[SHMSZ] = {0};
    shmADT s;
    int com, aux;

    sprintf(answ, "1,%d", COM_SND_DIRLIST);
    if((s = open_conn_shm(shmKey, 1)) == NULL)
    {
        fatal("open shm\n");
    }
    send_data_shm (s, answ, strlen(answ));

    /*TODO: DEBUG */
    printf("ENVIO: %s\n", answ);

    while(!msgForServer(s))
        ;
    rcv_data_shm (s, r_msg);
    sscanf(r_msg, "%d,%d", &aux, &com);

    if(com != COM_ACK)
    {
        fatal("Error msg received\n");
    }

    if ( sndlistSM(s) < 0 )
    {
        fatal ("List could not be sent correctly\n");
    }

    addLogSM(priv, "List dirs");

    while(!msgForServer(s))
        ;
    clrtext(r_msg, SHMSZ);
    rcv_data_shm (s, r_msg);
    sscanf(r_msg, "0,%d", &com);

    if (com == COM_ACK)
        close_conn_shm(s);
    return;
}


void adddirSM (char * dir, char * priv, int shmKey)
{
    int len, back, cliID, resp;

    char path[MAX_DIR_LEN + 7] = {0};
    queueADT dirs;
    int qlen, flag = 1;
    char *aux_dir;
    char logact[100] = {0};
    char keyC[100] = {0};
    char msg[SHMSZ] = {0};
    shmADT s;

    if((s = open_conn_shm(shmKey, 1)) == NULL)
        fatal("open shared memory failed\n");

    cliID = userID(priv);
    dirs = listDir();
    qlen = queueLength(dirs);

    if(isSynched(cliID, dir))
    {
        sprintf(msg, "1,%d", IS_SYNC);
        send_data_shm(s, msg, strlen(msg));
        return;
    }

    

    while(qlen-- && flag)
    {
        aux_dir = (char *)dequeue ( dirs );
        if (strcmp(dir, aux_dir) == 0)
            flag = 0;
        free(aux_dir);
    }
    if (flag)
    {
    	clrtext(msg, SHMSZ);
        sprintf(msg, "1,%d", DIR_ERR);
        send_data_shm(s, msg, strlen(msg));
        return;
    }

    len = strlen(dir);

	clrtext(msg, SHMSZ);
    sprintf(msg, "1,%d,%d,%s", COM_SND_FILES, len, dir);
    send_data_shm(s, msg, strlen(msg));

    while(!msgForServer(s))
        ;
    clrtext(msg, SHMSZ);
    rcv_data_shm(s, msg);

    printf("MSG: %s\n", msg);

    sscanf(msg, "0,%d", &back);

    fprintf(stderr, "%d received\n", back);

//  TODO addFifoDir debe hacer algo con la db.... no estoy
// seguro, pero la puse por las dudas siguiendome de ejemplo con msgQ
    sprintf(keyC, "%d", shmKey);
    resp = addFifoDir(keyC,dir);

    sprintf (path, "./%s", dir);
    if(walkDirSM(path, "", s, s) <= 0)
        fatal("Dir send failed\n");

    clrtext(msg, SHMSZ);
    sprintf(msg, "1,%d,trash", COM_END);
    send_data_shm(s, msg, strlen(msg));
    strcpy(logact, "Sync dir: ");
    strcat(logact, dir);
    addLogSM(priv, logact);

    while(!msgForServer(s))
        ;
    clrtext(msg, SHMSZ);
    rcv_data_shm(s, msg);

    sscanf(msg, "0,%d", &back);
    if (back == COM_ACK)
        close_conn_shm(s);

    return;
}

void removedirSM (char * dir, char * priv, int shmKey)
{
    DB_ERR ans;
    char logact[100] = {0};
    int len, back;
    char answ[MSGSIZE] = {0};
    char msg[MSGSIZE] = {0};
    char shmKeyC[MSGSIZE] = {0};
    shmADT s;

    sprintf(shmKeyC, "%d", shmKey);
    if((s = open_conn_shm(shmKey, 1)) == NULL)
        fatal("open shared memory failed\n");

    if ((ans = removeDirByFifo(shmKeyC, dir)) != DB_SUCCESS)
    {
        sprintf(answ, "1,%d,trash", COM_ERR);
        len = strlen(answ);
        send_data_shm(s, answ, len);
        fatal(  "ERROR: DB failure.\n"
                "SOLUTION: Check server's removedirPI.\n");
    }

    strcpy (logact, "Remove sync: ");
    strcat(logact, dir);
    addLogSM(priv, logact);

    len = strlen(dir);
    clrtext(answ, MSGSIZE);
    sprintf(answ, "1,%d,%d,%s", COM_RMV_OK, len, dir);
    len = strlen(answ);

    send_data_shm(s, answ, len);

    while(!msgForServer(s))
        ;
    clrtext(msg, MSGSIZE);
    rcv_data_shm(s, msg);

    sscanf(msg, "0,%d", &back);
    printf("BACK: %d\n", back);
    if (back == COM_ACK)
        close_conn_shm(s);

    return;
}

void closesessSM (char * priv)
{
    return;
}

void rcvCommitSM (char * params, char * priv, int privKey)
{
    int type, len, comm, size, nread, fsize;
    char dir[FILE_LEN] = {0};
    char path[100] = {0};
    char newpath[100] = {0};
    char answ[SHMSZ+1] = {0};
    char logact[100] = {0};
    FILE * pfile;
    shmADT s;

    if((s = open_conn_shm(privKey, 1)) == NULL)
        return;

    getDirType(params, dir, &type);

    if(type == ADD_MOD)
    {
        len = strlen(dir);
        sprintf(answ, "1,%d,%d,%s", COM_RCV_COMMIT, len, dir);

        send_data_shm(s, answ, strlen(answ));

        while(!msgForServer(s))
            ;
		clrtext(answ, SHMSZ);
        rcv_data_shm(s, answ);

        printf("MSG: %s\n", answ);
        sscanf(answ, "0,%d", &comm);

        if(comm != COM_ACK)
        {
            printf("Error receiving data\n");
            return;
        }

        clrtext(answ, SHMSZ);
        sprintf(answ, "1,%d", COM_ACK);
        send_data_shm(s, answ, strlen(answ));

        while(!msgForServer(s))
            ;

        clrtext(answ, SHMSZ);
        rcv_data_shm(s, answ);

        printf("MSG, %s\n", answ);
        sscanf(answ, "0,%d", &comm);

        if(comm == SND_FILE)
        {
            sscanf(answ, "0,%d,%d,%d,%s", &comm, &fsize, &size,path);
            printf("MSG: %s\n", answ);

            printf("SIZE: %d    PATH: %s\n", size, path);
            sprintf(newpath, "%s.new", path);

			clrtext(answ, SHMSZ);
            if (size == -1)
            {
                if(mkdir(path, 0777) == -1)
                {
                    printf("ERROR: creating dir: %s\n", path);
                    /* TODO: enviar COM_ERR */
//                    sndFifoAns(cliPriv, COM_ERR);
                    return ;
                }
                if (remove(newpath) != 0)
                {
                    printf("ERROR: removing dir: %s\n", newpath);
                    /* TODO: enviar COM_ERR */
//                    sndFifoAns(priv, COM_ERR);
                    return ;
                }
              
                sprintf(answ, "1,%d", COM_ACK);
                send_data_shm(s, answ, strlen(answ));
            }
            else
            {
                if((pfile = fopen(newpath, "w")) == NULL)
                    fatal ("Error creating file\n");

                nread = 0;
                sprintf(answ, "1,%d", COM_ACK);
                send_data_shm(s, answ, strlen(answ));
                while(size > 0)
                {
                    if (size >= BUF_SIZE)
                        nread = BUF_SIZE;
                    else
                        nread = size;

                    while(!msgForServer(s))
                        ;

                    clrtext(answ, SHMSZ+1);
                    rcv_data_shm(s, answ);

                    if((fwrite(answ+1, 1, nread, pfile)) < nread)
                    {
                        clrtext(answ, SHMSZ+1);
                        sprintf(answ, "1,%d", COM_ERR);
                        send_data_shm(s, answ, strlen(answ));
                        fatal("File write failed\n");
                    }

                    clrtext(answ, SHMSZ+1);
                    sprintf(answ, "1,%d", COM_ACK);
                    send_data_shm(s, answ, strlen(answ));

                    size -= nread;
                }

                if ((fclose (pfile)) == EOF)
                    fatal("file close failed\n");

                if (rename(newpath, path) != 0)
                {
                    printf("Error renaming %s\n", newpath);
                    return;
                }
            }
        }

        /*TODO: DEBUG */
        printf ("%s received OK\n", path);

        if ((srv_commitSM(s, path, type)) < 0)
        {
            printf("Error forwarding %s\n", path);
        }

        strcpy(logact, "Commited (add/mod): ");
        strcat (logact, path);

        addLogSM(priv, logact);

        clrtext(answ, SHMSZ+1);
        sprintf(answ, "1,%d", COM_ACK);
        send_data_shm(s, answ, strlen(answ));
        printf("TERMINO\n");

        while(!msgForServer(s))
            ;

        clrtext(answ, SHMSZ+1);
        rcv_data_shm(s, answ);
        printf("END: %s\n", answ);

    }
    else if(type == DEL_COMMIT)
    {
        if(remove(dir) != 0)
        {
            clrtext(answ, SHMSZ+1);
            sprintf(answ, "1,%d", COM_ERR);
            send_data_shm(s, answ, strlen(answ));
        }
        else
        {
            if(srv_commitSM(s, dir, type) < 0)
            {
                printf("Error forwarding %s\n", path);
            }

            strcpy(logact, "Commited (del): ");
            strcat (logact, dir);

            addLogSM(priv, logact);

            clrtext(answ, SHMSZ+1);
            sprintf(answ, "1,%d", COMMIT_OK);
            send_data_shm(s, answ, strlen(answ));
            printf("END0: %s\n", answ);

            
            while(!msgForServer(s))
                ;
			clrtext(answ, SHMSZ);
            rcv_data_shm(s, answ);
            printf("END: %s\n", answ);
        }
    }

    else if(type == DEL_DIR_COMMIT)
    {
        if(rmdir(dir) != 0)
        {
            clrtext(answ, SHMSZ+1);
            sprintf(answ, "1,%d", COM_ERR);
            send_data_shm(s, answ, strlen(answ));
        }
        else
        {
            if(srv_commitSM(s, dir, type) < 0)
            {
                printf("Error forwarding %s\n", path);
            }

            strcpy(logact, "Commited (del): ");
            strcat (logact, dir);

            addLogSM(priv, logact);

            clrtext(answ, SHMSZ+1);
            sprintf(answ, "1,%d", COMMIT_OK);
            send_data_shm(s, answ, strlen(answ));
            printf("END0: %s\n", answ);

            
            while(!msgForServer(s))
                ;
			clrtext(answ, SHMSZ);
            rcv_data_shm(s, answ);
            printf("END: %s\n", answ);
        }
    }

    close_conn_shm(s);
    return;
}

int srv_commitSM(shmADT s, char * path, int type)
{
    queueADT clients;
    int cant, len, back;
    char dir[MAX_DIR_LEN] = {0};
    char answ[SHMSZ] = {0};
    char ans[SHMSZ] = {0};
    char aux_msg[MSGSIZE+1] = {0};
    char * next_cliID;
    int next_shmKey, cliID;
    char keyC[MSGSIZE] = {0};
    shmADT next_s;

    getDir(dir, path);
    printf("dir: %s\n", dir);

    sprintf(keyC, "%d", getShmKey(s));
    clients = listUpdate(keyC, dir);
    cant = queueLength(clients);

    printf ("CANT: %d\n", cant);


    sprintf(aux_msg, "%s,%d", path, type);
    len = strlen((char *)aux_msg);
    sprintf(answ, "1,%d,%d,%s", COM_SND_COMMIT, len, aux_msg);

    printf ("UNO\n");
    len = strlen((char *)answ);

    while (cant--)
    {
        next_cliID = (char *)dequeue ( clients );
        cliID = userIDPI(next_cliID);
        while (!isFreeOnline(cliID))
            sleep(5);
        printf ("DOS\n");
        sscanf(next_cliID, "%d", &next_shmKey);

        if((next_s = open_conn_shm(next_shmKey, 1)) == NULL)
            fatal("open shared memory failed\n");

        printf ("TRES\n");
        send_data_shm(next_s, answ, len);

        while(!msgForServer(next_s))
            ;

        clrtext(ans, SHMSZ);
        rcv_data_shm(next_s, ans);

        if(type == ADD_MOD)
        {
            if(send_file_shm (next_s, next_s, path, 0, 1) < 0)
            {
                printf("%s not sent \n", path);
            }
        }
        free(next_cliID);

        clrtext(aux_msg, MSGSIZE + 1);
        sprintf(aux_msg, "1,%d", COM_END);
        len = strlen((char *)aux_msg);
        send_data_shm(next_s, aux_msg, len);

        while(!msgForServer(next_s))
            ;

        clrtext(ans, SHMSZ);
        rcv_data_shm(next_s, ans);
        sscanf(ans, "0,%d", &back);
        printf("ENDSRV: %s\n", ans);
        if(back == COM_END)
            close_conn_shm(next_s);
    }

    freeQueue( clients );
    return 1;
}


void salirSM(char * param)
{
    return;
}

void getparamSM (char * full, char * params, char * priv)
{
    char c;

    c = *full++;
    while (c != ',' && c != 0)
    {
        *priv++ = c;
        c = *full++;
    }
    if (c == 0)
        return ;

    strcpy(params, full);
    return;
}

int sndlistSM(shmADT s)
{
    queueADT dirs;
    int cant;
    int name_len, tot_len;

    char answ[SHMSZ] = {0};
    int back;
    char * name;

    dirs = listDir();
    cant = queueLength(dirs);

    /*TODO: DEBUG */
    printf ("CANT: %d\n", cant);

    while (cant--)
    {
        name = (char *)dequeue ( dirs );
        name_len = strlen( name);
        sprintf(answ, "1,%d,%d,%s", SND_DIR_NAME, name_len, name);

        tot_len = strlen (answ);

        do
        {
            /*TODO: DEBUG */
            printf("OK\n");
            send_data_shm (s, answ, tot_len);

            while(!msgForServer(s))
                ;

			clrtext(answ, SHMSZ);
            rcv_data_shm(s, answ);
            sscanf(answ, "0,%d", &back);
            /*TODO: DEBUG */
            printf("ACA: %d\n", back);

        }while (back != COM_ACK);
    }


    freeQueue( dirs );
	
	clrtext(answ, SHMSZ);
    sprintf(answ, "1,%d,trash", COM_END);
    send_data_shm(s, answ, strlen(answ));

    return 1;
}

void closeALLSM(void)
{
    queueADT q = NULL;
    int *index = NULL;
    int stat;

    printf("Closing splits.");
    doLC = 0;

    if (splitVal == 't')
    {
        q = getUsedOnline();

        while((index = dequeue(q)) != NULL)
        {
            pthread_join(splits[*index].thread, NULL);
             printf(".");
            free(index);
        }
        freeQueue(q);
    }
    else
    {
        /*HACK: Mando senial para salir del select*/
        kill(splits[0].cID, SIGUSR1);
        while ((waitpid (-1, &stat, 0)) > 0)
            printf(".");
    }

    printf("\nServer closed\n");
    exitSplit(splitVal);
}

void
sighandLCSM(int signo)
{
    closeALLSM();
}

void
endCiclesSM(int signo)
{
    doLC = 0;
    return;
}
